﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TI_4_Limonade_Fabriek.Database;
using TI_4_Limonade_Fabriek.Logging;
using TI_4_Limonade_Fabriek.Model;
using TI_4_Limonade_Fabriek.OPC;
using System.Windows.Forms;

namespace TI_4_Limonade_Fabriek
{
    class BatchController
    {
        OPCController OpcController;
        BatchLogging bl;
        BatchDBController bdbc;
        ErrorLogging el;
        private List<Batch> batchList;
        private List<Tag> statusTagList;
        public bool stoppen = false;

        public BatchController()
        {
            //connectie opzetten.
            bl = new BatchLogging();
            el = new ErrorLogging();
            bdbc = new BatchDBController();
            batchList = new List<Batch>();
            statusTagList = new List<Tag>();
            statusTagList.Add(new Tag("NOODSTOP", false));
            statusTagList.Add(new Tag("HMI_PAUZE", false));
            statusTagList.Add(new Tag("HMI_STOP", false));
        }

        //Controleer of er een batch klaar is.
        public void BatchPLC()
        {
                // Als links klaar is, schrijf deze weg naar de log.
                if (OpcController.ReadTags("L_K") == "True")
                {
                    string linksMengverhouding = OpcController.ReadTags("L_MV");
                    string linksBekers = OpcController.ReadTags("L_BEKERS");
                    string linksRood = OpcController.ReadTags("K_L_R");
                    string linksGroen = OpcController.ReadTags("K_L_G");
                    string linksOranje = OpcController.ReadTags("K_L_O");
                    string linksKleur = "";

                    if (linksRood == "True")
                    {
                        linksKleur = "Rood";
                    }
                    else if (linksGroen == "True")
                    {
                        linksKleur = "Groen";
                    }
                    else if (linksOranje == "True")
                    {
                        linksKleur = "Oranje";
                    }

                    Batch batch = new Batch { Mengverhouding = Int32.Parse(linksMengverhouding), AantalBekers = Int32.Parse(linksBekers), Kleur = linksKleur, Status = 1, };

                    batch = BatchCompare(batch);
                    if (batch != null)
                    {
                        
                        bl.WriteBatchLog(batch);
                        bdbc.DeleteBatch(batch.BId);
                        OpcController.WriteTags("L_K", 0);
                        
                    }

                }
                // Als rechts klaar is, schrijf deze weg naar de log.
                else if (OpcController.ReadTags("R_K") == "True")
                {
                    string rechtsMengverhouding = OpcController.ReadTags("R_MV");
                    string rechtsBekers = OpcController.ReadTags("R_BEKERS");
                    string rechtsRood = OpcController.ReadTags("K_R_R");
                    string rechtsGroen = OpcController.ReadTags("K_R_G");
                    string rechtsOranje = OpcController.ReadTags("K_R_O");
                    string rechtsKleur = "";
                              
                    if (rechtsRood == "True")
                    {
                        rechtsKleur = "Rood";
                    }
                    else if (rechtsGroen == "True")
                    {
                        rechtsKleur = "Groen";
                    }
                    else if (rechtsOranje == "True")
                    {
                        rechtsKleur = "Oranje";
                    }

                    Batch batch = new Batch { Mengverhouding = Int32.Parse(rechtsMengverhouding), AantalBekers = Int32.Parse(rechtsBekers), Kleur = rechtsKleur, Status = 1, };

                    batch = BatchCompare(batch);
                    if (batch != null)
                    {
                        bl.WriteBatchLog(batch);
                        bdbc.DeleteBatch(batch.BId);
                        OpcController.WriteTags("R_K", 0);
                    }
                }
        }

        //Vergelijk de batch in de OPC met de batches in de database.
        public Batch BatchCompare(Batch plcBatch)
        {
            List<Batch> compareList = new List<Batch>();
            compareList = bdbc.ReadBatchList();
            foreach (Batch databaseBatch in compareList)
            {
                if (plcBatch.Kleur == databaseBatch.Kleur && plcBatch.Mengverhouding == databaseBatch.Mengverhouding && plcBatch.AantalBekers == databaseBatch.AantalBekers && databaseBatch.Status == 1)
                {
                    //Als de batch overeen komt, return de waarde van deze batch.
                    plcBatch = databaseBatch;
                    return plcBatch;
                }
            }
            return null;
        }

        //Controleer of de pauze, stop of noodstop actief is.
        public void CheckStatusPLC()
        {
            bool tagValuePLC;

            foreach (Tag entry in statusTagList)
            {
                tagValuePLC = Convert.ToBoolean(OpcController.ReadTags(entry.TagName));

                //invert noodstop, false = noodstop ingedrukt.
                if (entry.TagName == "NOODSTOP")
                    tagValuePLC = !tagValuePLC;

                if (tagValuePLC == true)
                {
                    if (entry.TagValue == false)
                    {
                        entry.TagValue = true;
                        //Als of de noodstop, pauze of stop actief is, schrijf dit naar de log.
                        switch (entry.TagName) 
                        {
                            case "NOODSTOP":
                                el.LogErrorMsg("Noodstop is actief");
                                break;
                            case "HMI_PAUZE":
                                el.LogErrorMsg("Opstelling is gepauzeerd");
                                break;
                            case "HMI_STOP":
                                el.LogErrorMsg("Opstelling is gestopt");
                                break;
                            default:
                                //Mocht er een andere melding zijn, schrijf deze ook weg.
                                el.LogErrorMsg("Er is een fout opgetreden met: " + entry.TagName);
                                break;
                        }
                    }
                }
                else
                {
                    if (entry.TagValue == true)
                        entry.TagValue = false;
                }
            }
        }

        //Verwerkt de batches naar de OPC.
        public void Uitvoeren() 
        {
            //Als Vraag batch waar is, stuur een nieuwe batch naar de PLC.
                if (OpcController.ReadTags("V_B") == "True") 
                {
                    batchList = bdbc.ReadBatchList();

                    if ((batchList.Count() == 0 || (batchList.Count() == 1 && (batchList[0].Status == 1 || batchList[0].Datum != System.DateTime.Now.ToString("dd-MM-yyyy"))) && OpcController.ReadTags("G_B") == "False"))
                    {
                        OpcController.WriteTags("G_B", 1);
                        OpcController.WriteTags("V_B", 0);
                    }
                    else if (batchList.Count() != 0)
                    {
                        int batchIndex = 0;
                        foreach (Batch batch in batchList)
                        {
                            batchIndex++;

                            if (batch.Status == 0)
                            {


                                WriteOPC(batch);
                                batch.Status = 1;
                                bdbc.UpdateBatch(batch);
                                // Als er een volgende batch is, schrijf deze naar de PLC voor de HMI.
                                if (batchList.Count() > batchIndex)
                                    WriteHMI(batchList[batchIndex]);
                                else
                                    WriteHMI(null);

                                break;
                            }
                        }
                    }
                }
            
        }

        //Schrijft één tag naar de OPC.
        public void WriteOPC(Batch b)
        {
            OpcController.WriteTags("OPC_1", b.Mengverhouding);
            OpcController.WriteTags("OPC_2", b.AantalBekers);

            switch (b.Kleur)
            {
                case "Rood":
                    OpcController.WriteTags("OPC_R", 1);
                    OpcController.WriteTags("OPC_G", 0);
                    OpcController.WriteTags("OPC_O", 0);
                    break;
                case "Groen":
                    OpcController.WriteTags("OPC_R", 0);
                    OpcController.WriteTags("OPC_G", 1);
                    OpcController.WriteTags("OPC_O", 0);
                    break;
                case "Oranje":
                    OpcController.WriteTags("OPC_R", 0);
                    OpcController.WriteTags("OPC_G", 0);
                    OpcController.WriteTags("OPC_O", 1);
                    break;

                default:
                    OpcController.WriteTags("OPC_R", 0);
                    OpcController.WriteTags("OPC_G", 0);
                    OpcController.WriteTags("OPC_O", 0);
                    break;
            }
            OpcController.WriteTags("V_B", 0);
        }

        //Schrijft de HMI bits naar de OPC.
        public void WriteHMI(Batch b)
        {
            if (b != null)
            {
                OpcController.WriteTags("HMI_V_MV", b.Mengverhouding);
                OpcController.WriteTags("HMI_V_BEKERS", b.AantalBekers);

                switch (b.Kleur)
                { 
                    case "Rood":
                        OpcController.WriteTags("HMI_V_R", 1);
                        OpcController.WriteTags("HMI_V_G", 0);
                        OpcController.WriteTags("HMI_V_O", 0);
                        break;
                    case "Groen":
                        OpcController.WriteTags("HMI_V_R", 0);
                        OpcController.WriteTags("HMI_V_G", 1);
                        OpcController.WriteTags("HMI_V_O", 0);
                        break;
                    case "Oranje":
                        OpcController.WriteTags("HMI_V_R", 0);
                        OpcController.WriteTags("HMI_V_G", 0);
                        OpcController.WriteTags("HMI_V_O", 1);
                        break;

                    default:
                        OpcController.WriteTags("HMI_V_R", 0);
                        OpcController.WriteTags("HMI_V_G", 0);
                        OpcController.WriteTags("HMI_V_O", 0);
                        break;
                }
            }
            else
            {
                OpcController.WriteTags("HMI_V_MV", 0);
                OpcController.WriteTags("HMI_V_BEKERS", 0);
                OpcController.WriteTags("HMI_V_R", 0);
                OpcController.WriteTags("HMI_V_G", 0);
                OpcController.WriteTags("HMI_V_O", 0);
            }
        }

        // Verwerkt BatchPLC, Uitvoeren en CheckstatusPLC na elkaar om conflicten te voorkomen
        public void Sequiencieel()
        {
            OpcController = new OPCController("Group");
            while (!stoppen)
            {
                BatchPLC();
                Uitvoeren();
                CheckStatusPLC();
            }
            OpcController.Stop();
        } 
    }
}
